package com.yc;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Demo1 extends Demo1Parent{

    public static void main(String[] args)
            throws Exception {
        Class c0 = Demo1.class;
        Demo1 demo1 = new Demo1();
        Class c1 = demo1.getClass();
        Class c2 = Class.forName("com.yc.Demo1");

        System.out.println(c0 == c1);
        System.out.println(c2 == c1);

        /*
            类的构成元素:
            1. 属性
            2. 方法
            3. 构造方法
            4. 块 => 无名构造函数
            5. 内部类
         */
        c0.getFields(); // 全部共有属性
        c0.getMethods(); // 全部共有方法
        c0.getConstructors(); // 构造函数
        c0.getDeclaredClasses(); //内部类


        c0.getFields();              // 全部共有属性
        c0.getField("a");  // 指定名称的共有属性
        c0.getDeclaredField("a");  // 指定名称定义的属性
        c0.getDeclaredFields();     // 所有定义的属性

        System.out.println("========全部共有属性=========");
        for (Field field : c0.getFields()) {
            System.out.println("field = " + field);
        }
        System.out.println("========全部定义的属性=========");
        for (Field field : c0.getDeclaredFields()) {
            System.out.println("field = " + field);
        }
        System.out.println("========当前类的全部属性包括父类非共有=========");
        Class c = c0;
        while(c!=null){
            for (Field field : c.getDeclaredFields()) {
                System.out.println("field = " + field);
            }
            // 父类
            c = c.getSuperclass();
        }

        ///////////////////////////////////////////
        System.out.println("========反射操作对象=========");
        User user = new User();
        test(user);
    }

    public String a;
    protected String b;
    private String c;
    String d;

    public static void test(Object obj)
            throws NoSuchFieldException,
            IllegalAccessException,
            NoSuchMethodException,
            InvocationTargetException {
        Class<?> aClass = obj.getClass();
        // getName 全名
        if("com.yc.User".equals(aClass.getName())){
            Field name = aClass.getDeclaredField("name");
            // 强制访问, 可以访问私有属性
            name.setAccessible(true);
            name.set(obj,"张三");

            // 调用无参数方法
            Method hello = aClass.getDeclaredMethod("hello");
            hello.setAccessible(true);
            hello.invoke( obj);
            // 调用有参数方法
            Method hello1 = aClass.getDeclaredMethod("hello", String.class);
            hello1.setAccessible(true);
            hello1.invoke( obj, "李四");

            System.out.println("obj.toString() = " + obj.toString());
        }
    }

}

class Demo1Parent{
    public String a1;
    protected String b1;
    private String c1;
    String d1;
}


@Data  // 自动生成 get,set,toString,equals,hashcode方法
@AllArgsConstructor // 全部属性构造函数
@NoArgsConstructor  // 无参构造函数
class User {
    private String name;
    private String pwd;
    private Integer age;

    private void hello(){
        System.out.println("hello " + name);
    }

    private void hello(String myname){
        System.out.println("hello " + myname);
    }
}

